/**
 * 延迟调用类成员函数或回调函数
 * 用于延迟调用，或非UI线程操作UI元素
 * 被延迟调用的函数将稍后在UI线程被调用
 *
 * 使用方法：(回调函数)
      callLater(CALL_LATER_LAMBDA {
          // 代码块
      });
 */

#ifndef CALLLATER_H
#define CALLLATER_H

#include <QObject>
#include <QVariant>
#include <functional>

#define CALL_LATER_LAMBDA [&] (QVariant)
#define CALL_LATER_LAMBDA_ARG [&] (QVariant arg)

class CallLater : public QObject
{
    Q_OBJECT

public:
    typedef std::function<void (QVariant)> Callback;

    struct CallInfo {
        bool isMethod;
        QObject *obj;
        const char *method;
        Callback callback;
        QVariant arg;

        CallInfo()
        {
            isMethod = true;
            obj = nullptr;
            method = nullptr;
            callback = nullptr;
        }

        CallInfo(QObject *obj, const char *method, QVariant arg)
        {
            isMethod = true;
            this->obj = obj;
            this->method = method;
            callback = nullptr;
            this->arg = arg;
        }

        CallInfo(Callback callback, QVariant arg)
        {
            isMethod = false;
            obj = nullptr;
            method = nullptr;
            this->callback = callback;
            this->arg = arg;
        }
    };

    static CallLater &getInstance();

signals:
    void callLater(CallInfo info);

private:
    explicit CallLater(QObject *parent = nullptr);

    CallLater(const CallLater &) = delete;
    const CallLater &operator=(const CallLater &) = delete;

private slots:
    void onCallLater(CallInfo info);
};

Q_DECLARE_METATYPE(CallLater::CallInfo);

static inline void callLater(QObject *obj, const char *method, QVariant arg = QVariant())
{
    CallLater::CallInfo info(obj, method, arg);
    emit CallLater::getInstance().callLater(info);
}

static inline void callLater(CallLater::Callback callback, QVariant arg = QVariant())
{
    CallLater::CallInfo info(callback, arg);
    emit CallLater::getInstance().callLater(info);
}

#endif // CALLLATER_H
